//
//  AsmanVideoRecordViewModel.swift
//  vr_web
//
//  Created by 李旭峰 on 2020/7/13.
//

import UIKit
import AVFoundation
import RxSwift
import RxCocoa
import FCUUID

class AsmanVideoRecordViewModel: BaseViewModel {
    
    /// 音频录制状态
    enum AudioRecordStatus {
        /// 无效状态
        case kInvalid
        /// 正在录制
        case kRecording
        /// 正在播放
        case kPlaying
        /// 录制完成
        case kFinished
    }
    /// 每秒执行次数
    var handleLinkTimer:Int = 10{
        didSet{
            self.recordLink?.preferredFramesPerSecond = self.handleLinkTimer
            self.playLink?.preferredFramesPerSecond = self.handleLinkTimer
        }
    }
    /// 最大录制时长为90秒
    let MaxRecordTime:NSNumber = 90
    let currentRecordTimeSignal = BehaviorRelay<NSNumber>(value: 0)
    let currentPlayTimerSignal = BehaviorRelay<NSNumber>(value: 0)
    var timer:Timer?
    fileprivate var recordLink:CADisplayLink?
    fileprivate var playLink:CADisplayLink?
    var recorder:AVAudioRecorder?
    var player:AVAudioPlayer?
    let recordStatusSignal = BehaviorRelay<AudioRecordStatus>(value: .kInvalid)
    lazy var filePath:String = {
        let tempUUID = FCUUID.uuid()!
        let file_path = NSTemporaryDirectory().appending("audio_record.wav")
        return file_path
    }()
    
    override init() {
        super.init()
        self.recordLink = CADisplayLink(target: self, selector: #selector(onHandleRecordTimer))
        self.recordLink?.preferredFramesPerSecond = self.handleLinkTimer
        self.recordLink?.add(to: RunLoop.current, forMode: RunLoop.Mode.default)
        self.recordLink?.isPaused = true
        self.playLink = CADisplayLink(target: self, selector: #selector(onHandlePlayTimer))
        self.playLink?.preferredFramesPerSecond = self.handleLinkTimer
        self.playLink?.add(to: RunLoop.current, forMode: RunLoop.Mode.default)
        self.playLink?.isPaused = true
    }
    deinit {
        self.recordLink?.invalidate()
        self.recordLink = nil
        self.playLink?.invalidate()
        self.playLink = nil
    }
    func checkAuthoriztion(didCompleted:@escaping (Bool)->()){
        let status = AVCaptureDevice.authorizationStatus(for: AVMediaType.audio)
        if (status == .authorized){
            print("Authorized")
            didCompleted(true)
            return
        }
        if (status == .notDetermined){
            print("Not determined")
        }
        if (status == .restricted)
        {
            print("restricted")
        }
        if (status == .denied){
            print("denied")
        }
        // 获取麦克风权限
        AVCaptureDevice.requestAccess(for: AVMediaType.audio, completionHandler: { (granted: Bool) -> Void in
            didCompleted(granted)
        })
    }
    func beginRecord(didCompleted:(Bool,String)->()){
        let session = AVAudioSession.sharedInstance()
        // 设置session类型
        if session.category != .record {
            try? session.setCategory(AVAudioSession.Category.record)
        }
        // 设置session动作
        do{
            try session.setActive(true, options: [])
        }catch let err {
            didCompleted(false,"初始化动作失败:\(err.localizedDescription)")
            return
        }
        // 录音设置，注意：需要转换成Number类型，否则无法录制音频文件
        let recordSetting:[String:Any] =  [AVSampleRateKey: NSNumber(value: 8000),//采样率
            AVFormatIDKey: NSNumber(value: kAudioFormatLinearPCM),//音频格式
            AVLinearPCMBitDepthKey: NSNumber(value: 16),//采样位数
            AVNumberOfChannelsKey: NSNumber(value: 1),//通道数
            AVEncoderAudioQualityKey: NSNumber(value: AVAudioQuality.min.rawValue)]//录音质量
        // 开始录制
        do{
            let url = URL(fileURLWithPath: filePath)
            self.recorder = try AVAudioRecorder(url: url, settings: recordSetting)
            self.recorder?.prepareToRecord()
            self.recorder?.record()
            didCompleted(true,"")
            self.currentRecordTimeSignal.accept(0)
            self.recordLink?.isPaused = false
        }catch let err {
            didCompleted(false,"录音失败: \(err.localizedDescription)")
            return
        }
    }
    func stopRecord(){
        if let tempRecorder = self.recorder,tempRecorder.isRecording {
            self.recorder = nil
            self.recordLink?.isPaused = true
            tempRecorder.stop()
        }
    }
    func deleteRecord(){
        let fileManager = FileManager.default
        let exist = fileManager.fileExists(atPath: self.filePath)
        if exist {
            do {
                try FileManager.default.removeItem(atPath: self.filePath)
            }catch let err {
                print("文件删除失败:\(err.localizedDescription)")
            }
        }
    }
    func play(didCompleted:(Bool,String)->()){
        do{
            let session = AVAudioSession.sharedInstance()
            // 设置session类型
            if session.category != .ambient {
                try? session.setCategory(AVAudioSession.Category.ambient)
            }
            // 设置session动作
            do{
                try session.setActive(true, options: [])
            }catch let err {
                didCompleted(false,"初始化动作失败:\(err.localizedDescription)")
                return
            }
            let url = URL(fileURLWithPath: self.filePath)
            self.player = try AVAudioPlayer(contentsOf: url)
            self.player?.play()
            self.player?.delegate = self
            didCompleted(true,"")
            self.currentPlayTimerSignal.accept(0)
            self.playLink?.isPaused = false
        }catch let err {
            didCompleted(false,"播放失败：\(err.localizedDescription)")
            return
        }
    }
    func stopPlay(){
        self.player?.pause()
        self.playLink?.isPaused = true
    }
    func createMp3File(didCompleted:@escaping (String?,String?) -> ()) {
        didCompleted(self.filePath,nil)
    }
    
    @objc func onHandleRecordTimer(){
        let currentTimer = self.currentRecordTimeSignal.value
        if currentTimer >= self.MaxRecordTime {
            self.stopRecord()
            self.recordStatusSignal.accept(.kFinished)
            return
        }
        let timeOffset = 1 / self.handleLinkTimer.number
        self.currentRecordTimeSignal.accept(currentTimer + timeOffset)
    }
    @objc func onHandlePlayTimer(){
        let currentTimer = self.currentPlayTimerSignal.value
        let timeOffset = 1 / self.handleLinkTimer.number
        self.currentPlayTimerSignal.accept(currentTimer + timeOffset)
    }
    
}

extension AsmanVideoRecordViewModel : AVAudioPlayerDelegate {
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        self.recordStatusSignal.accept(.kFinished)
        self.playLink?.isPaused = true
        self.currentPlayTimerSignal.accept(self.currentRecordTimeSignal.value)
    }
}
